<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            overflow: hidden;
        }

        #mark {
            position: absolute;
            transform: translate(-50%, -50%);
            top: 0;
            left: 0;
            color: #fff;
            background-color: rgba(0, 0, 0, 0.6);
            padding: 6px 12px;
            border-radius: 3px;
            user-select: none;
        }
    </style>
</head>

<body>
    <canvas id="canvas"></canvas>
    <div id="mark">标记点</div>
</body>
<script id="ColorVS" type="x-shader/x-vertex">
    attribute vec4 a_Position;
    attribute vec2 a_Pin;
    uniform mat4 u_ModelM4;
    uniform mat4 u_PvM4;
    varying vec2 v_Pin;
    void main(){
        gl_Position = u_PvM4 * u_ModelM4 * a_Position;
        v_Pin = a_Pin;
    }
</script>
<script id="ColorFS" type="x-shader/x-fragment">
    precision mediump float;
    uniform sampler2D u_Texture;
    uniform vec4 u_Color;
    varying vec2 v_Pin;
    void main(){
        gl_FragColor = texture2D(u_Texture, v_Pin);
        //gl_FragColor = u_Color;
    }
</script>

<script type="module">
    import { Matrix4, Vector3, Euler, OrthographicCamera, PerspectiveCamera, Spherical } from '../js/three.module.js';
    import { CreateProgram, imgPromise } from '../js/Utils.js';
    import lib from '../js/ThreeLib.js';
    import CameraController from '../js/CameraController.js'
    import Poly from '../js/Poly4.js'
    import Control from '../js/Control.js'
    import Earth from '../js/objs/Earth.js'
    import Gyro from '../js/Gyro.js'
    import Animate from '../js/Animate.js'

    import Geo from '../js/Poly2/Geo.js'
    import Mat from '../js/Poly2/Mat.js'
    import Obj3D from '../js/Poly2/Obj3D.js'
    import Scene from '../js/Poly2/Scene.js'




    //#region gl
    const canvas = document.getElementById("canvas");
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;

    const gl = canvas.getContext("webgl", { antialias: true, });

    gl.enable(gl.BLEND);
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
    gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);//去图片描边
    gl.enable(gl.DEPTH_TEST);
    //#endregion

    const scene = new Scene({ gl: gl });
    scene.addAxisProgram();
    scene.regProgram('color', {
        program: CreateProgram(gl,
            document.querySelector('#ColorVS').innerText,
            document.querySelector('#ColorFS').innerText),
        attribs: ['a_Position', 'a_Pin'],
        uniforms: ['u_PvM4', 'u_ModelM4', 'u_Texture', 'u_Color']
    });


    const pvM4 = new Matrix4();
    const modelM4 = new Matrix4();
    const eye = new Vector3(0, 0.45, 0.0);
    const lookAt = new Vector3();

    const curEye = eye.clone();//用于陀螺仪的旋转
    const animate = new Animate();


    const camera = new PerspectiveCamera(120, canvas.width / canvas.height, 0.1, 20);
    const cameraController = new CameraController({
        canvas,
        camera,
        pvMatrix: pvM4,
        eye,
        lookAt,
        orZoom: true,
        MoveEvent: false,
        // RotateEvent: false,
        // ScaleEvent: false,
    });



    const axis = new Obj3D().createAxis('axis');
    // scene.add(axis);




    const earth = new Earth(0.5, 64, 32);
    const [vertices, elements, normals, uv] = [
        earth.vertices, earth.elements, earth.normals, earth.uv
    ];

    const earthGeo = new Geo({
        data: {
            'a_Position': { size: 3, array: new Float32Array(vertices) },
            'a_Pin': { size: 2, array: new Float32Array(uv) },
        },
        element: { array: new Uint16Array(elements) }
    });
    const earthMat = new Mat({
        program: 'color',
        mode: ['TRIANGLES'],
        data: {
            'u_PvM4': { type: 'uniformMatrix4fv', value: pvM4.elements },
            'u_ModelM4': { type: 'uniformMatrix4fv', value: modelM4.elements },
            'u_Color': { type: 'uniform4fv', value: [1, 0, 1, 1] },
        }
    });

    const titleArr = [];
    const box3D = new Obj3D({ geo: earthGeo, mat: earthMat });
    scene.add(box3D);


    const loadImage = function (index) {
        const earthImage = new Image();
        earthImage.src = `../Image/room${index}.jpg`;
        earthImage.addEventListener('load', function () {
            if (index == 0) {
                box3D.addTexureNew(gl, {
                    'u_Texture': {
                        image: earthImage,
                        MIN_FILTER: gl.LINEAR,
                        MAG_FILTER: gl.LINEAR,
                    }
                });
            } else {
                box3D.setMap('u_Texture', { image: earthImage, });
            }
            if (index < 3) {
                index++;
                loadImage(index);
            }
        });
    };
    loadImage(0);

    const gyro = new Gyro({
        init: () => {
            animate.add({
                id: 1,
                from: eye.clone(),
                to: new Vector3(0, 0, 0.45),
                from1: camera.fov,
                to1: 60,
                time: 2000,
                action: (p, data) => {
                    data.from = data.to.clone().sub(data.from).multiplyScalar(0.025).add(data.from);
                    cameraController.setEye(data.from);
                    data.from1 = (data.to1 - data.from1) * 0.05 + data.from1;
                    camera.fov = data.from1;
                    if (p == 1) {
                        cameraController.setEye(data.to);
                        camera.fov = data.to1;
                    }
                },
            });
        },
        change: (euler) => {
            eye.copy(curEye.clone().applyEuler(euler));
            cameraController.setEye(eye);
        }
    });
    gyro.start();

    const mark = document.querySelector('#mark');
    const markPosi = new Vector3();

    //#region 打标记
    canvas.addEventListener('dblclick', function (e) {
        const { clientX, clientY } = e;
        const cur = lib.getViewToWorld(clientX, clientY, canvas, pvM4);
        markPosi.copy(getWorld(eye, cur, lookAt, earth.r));
        setMarkCp(clientX, clientY);

        console.log(markPosi.distanceTo(new Vector3()))
    });

    function setMarkCp(x, y) {
        mark.style.left = `${x}px`
        mark.style.top = `${y}px`
    }

    //eye, 鼠标的世界位, lookAt, r
    function getWorld(E, A, O, r) {
        const V = A.clone().sub(E).normalize();
        const OE = E.clone().sub(O);
        const b = V.clone().multiplyScalar(2).dot(OE);
        const c = OE.clone().dot(OE) - r * r;
        const lambda = (-b + Math.sqrt(b * b - 4 * c)) / 2;
        return V.clone().multiplyScalar(lambda).add(OE);
    }

    function updateMarkCp() {
        if (!markPosi) { return }

        //判断标记点在相机的正面还是背面
        const dot = markPosi.clone().sub(eye).dot(
            lookAt.clone().sub(eye)
        );
        mark.style.display = dot > 0 ? 'block' : 'none';

        // 将标记点的世界坐标转裁剪坐标
        const { x, y } = markPosi.clone().applyMatrix4(pvM4);
        // 将标记点的裁剪坐标转canvas坐标
        setMarkCp(
            (x + 1) * canvas.width / 2,
            (-y + 1) * canvas.height / 2
        )
    }
    cameraController.setPvM4Action.push(updateMarkCp);
    //#endregion

    (function ani(time) {

        animate.update(time);
        draw();
        requestAnimationFrame(ani)
    })(0);


    function draw() {
        scene.setUniform('u_PvM4', { value: pvM4.elements });
        scene.draw();
    }
</script>

</html>